/**
 * WebSocket 管理类
 * 用于管理无人机状态和信息的实时推送连接
 */

class WebSocketManager {
  constructor() {
    this.ws = null // WebSocket 实例
    this.url = '' // WebSocket 连接地址
    this.isConnected = false // 连接状态
    this.reconnectTimer = null // 重连定时器
    this.heartbeatTimer = null // 心跳定时器
    this.reconnectAttempts = 0 // 重连次数
    this.maxReconnectAttempts = 10 // 最大重连次数
    this.reconnectInterval = 3000 // 重连间隔（毫秒）
    this.heartbeatInterval = 30000 // 心跳间隔（毫秒）
    this.messageHandlers = new Map() // 消息处理器映射
    this.eventListeners = new Map() // 事件监听器映射
    this.messageQueue = [] // 离线消息队列
    this.maxQueueSize = 100 // 最大队列长度
  }

  /**
   * 初始化 WebSocket 连接
   * @param {string} url - WebSocket 服务器地址
   * @param {Object} options - 配置选项
   */
  connect(url, options = {}) {
    if (this.ws && this.ws.readyState === WebSocket.OPEN) {
      console.warn('[WebSocket] 已经建立连接，无需重复连接')
      return Promise.resolve()
    }

    this.url = url

    // 合并配置选项
    if (options.maxReconnectAttempts !== undefined) {
      this.maxReconnectAttempts = options.maxReconnectAttempts
    }
    if (options.reconnectInterval !== undefined) {
      this.reconnectInterval = options.reconnectInterval
    }
    if (options.heartbeatInterval !== undefined) {
      this.heartbeatInterval = options.heartbeatInterval
    }

    return new Promise((resolve, reject) => {
      try {
        this.ws = new WebSocket(url)

        // 连接成功
        this.ws.onopen = (event) => {
          console.log('[WebSocket] 连接成功:', url)
          this.isConnected = true
          this.reconnectAttempts = 0

          // 触发连接成功事件
          this.emit('connected', event)

          // 开始心跳
          this.startHeartbeat()

          // 发送离线队列中的消息
          this.flushMessageQueue()

          resolve(event)
        }

        // 接收消息
        this.ws.onmessage = (event) => {
          this.handleMessage(event)
        }

        // 连接关闭
        this.ws.onclose = (event) => {
          console.log('[WebSocket] 连接关闭:', event.code, event.reason)
          this.isConnected = false

          // 停止心跳
          this.stopHeartbeat()

          // 触发断开连接事件
          this.emit('disconnected', event)

          // 尝试重连
          if (!event.wasClean && this.reconnectAttempts < this.maxReconnectAttempts) {
            this.reconnect()
          }
        }

        // 连接错误
        this.ws.onerror = (error) => {
          console.error('[WebSocket] 连接错误:', error)
          this.isConnected = false

          // 触发错误事件
          this.emit('error', error)

          // 如果是初次连接失败，reject promise
          if (this.reconnectAttempts === 0) {
            reject(error)
          }
        }

      } catch (error) {
        console.error('[WebSocket] 创建连接失败:', error)
        reject(error)
      }
    })
  }

  /**
   * 处理接收到的消息
   * @param {MessageEvent} event - 消息事件
   */
  handleMessage(event) {
    try {
      let data = event.data

      // 尝试解析 JSON 格式的消息
      if (typeof data === 'string') {
        try {
          data = JSON.parse(data)
        } catch (e) {
          // 如果不是 JSON，保持原始字符串
        }
      }

      // 心跳响应
      if (data.type === 'pong') {
        return
      }

      // 无人机状态更新
      if (data.type === 'drone_status') {
        this.handleDroneStatus(data)
      }

      // 无人机位置更新
      else if (data.type === 'drone_position') {
        this.handleDronePosition(data)
      }

      // 无人机传感器数据
      else if (data.type === 'sensor_data') {
        this.handleSensorData(data)
      }

      // 告警信息
      else if (data.type === 'alert') {
        this.handleAlert(data)
      }

      // 触发消息事件
      this.emit('message', data)

      // 调用注册的消息处理器
      if (data.type && this.messageHandlers.has(data.type)) {
        const handlers = this.messageHandlers.get(data.type)
        handlers.forEach(handler => {
          try {
            handler(data)
          } catch (error) {
            console.error(`[WebSocket] 消息处理器错误 (${data.type}):`, error)
          }
        })
      }

    } catch (error) {
      console.error('[WebSocket] 处理消息失败:', error)
      this.emit('error', error)
    }
  }

  /**
   * 处理无人机状态更新
   * @param {Object} data - 状态数据
   */
  handleDroneStatus(data) {
    // 触发无人机状态更新事件
    this.emit('droneStatus', data)
    console.log('[WebSocket] 无人机状态更新:', data)
  }

  /**
   * 处理无人机位置更新
   * @param {Object} data - 位置数据
   */
  handleDronePosition(data) {
    // 触发无人机位置更新事件
    this.emit('dronePosition', data)
  }

  /**
   * 处理传感器数据
   * @param {Object} data - 传感器数据
   */
  handleSensorData(data) {
    // 触发传感器数据更新事件
    this.emit('sensorData', data)
  }

  /**
   * 处理告警信息
   * @param {Object} data - 告警数据
   */
  handleAlert(data) {
    // 触发告警事件
    this.emit('alert', data)
    console.warn('[WebSocket] 告警信息:', data)
  }

  /**
   * 发送消息
   * @param {Object|string} message - 要发送的消息
   * @returns {boolean} - 发送是否成功
   */
  send(message) {
    if (typeof message === 'object') {
      message = JSON.stringify(message)
    }

    if (this.ws && this.ws.readyState === WebSocket.OPEN) {
      try {
        this.ws.send(message)
        return true
      } catch (error) {
        console.error('[WebSocket] 发送消息失败:', error)
        this.addToQueue(message)
        return false
      }
    } else {
      console.warn('[WebSocket] 连接未建立，消息已加入离线队列')
      this.addToQueue(message)
      return false
    }
  }

  /**
   * 发送命令给无人机
   * @param {string} droneId - 无人机ID
   * @param {string} command - 命令类型
   * @param {Object} params - 命令参数
   */
  sendDroneCommand(droneId, command, params = {}) {
    const message = {
      type: 'drone_command',
      droneId,
      command,
      params,
      timestamp: Date.now()
    }
    return this.send(message)
  }

  /**
   * 订阅特定类型的消息
   * @param {string} type - 消息类型
   * @param {Function} handler - 处理函数
   */
  subscribe(type, handler) {
    if (!this.messageHandlers.has(type)) {
      this.messageHandlers.set(type, new Set())
    }
    this.messageHandlers.get(type).add(handler)

    // 返回取消订阅函数
    return () => {
      const handlers = this.messageHandlers.get(type)
      if (handlers) {
        handlers.delete(handler)
        if (handlers.size === 0) {
          this.messageHandlers.delete(type)
        }
      }
    }
  }

  /**
   * 取消订阅消息
   * @param {string} type - 消息类型
   * @param {Function} handler - 处理函数
   */
  unsubscribe(type, handler) {
    const handlers = this.messageHandlers.get(type)
    if (handlers) {
      handlers.delete(handler)
      if (handlers.size === 0) {
        this.messageHandlers.delete(type)
      }
    }
  }

  /**
   * 注册事件监听器
   * @param {string} event - 事件名称
   * @param {Function} listener - 监听函数
   */
  on(event, listener) {
    if (!this.eventListeners.has(event)) {
      this.eventListeners.set(event, new Set())
    }
    this.eventListeners.get(event).add(listener)

    // 返回移除监听器的函数
    return () => this.off(event, listener)
  }

  /**
   * 移除事件监听器
   * @param {string} event - 事件名称
   * @param {Function} listener - 监听函数
   */
  off(event, listener) {
    const listeners = this.eventListeners.get(event)
    if (listeners) {
      listeners.delete(listener)
      if (listeners.size === 0) {
        this.eventListeners.delete(event)
      }
    }
  }

  /**
   * 触发事件
   * @param {string} event - 事件名称
   * @param {any} data - 事件数据
   */
  emit(event, data) {
    const listeners = this.eventListeners.get(event)
    if (listeners) {
      listeners.forEach(listener => {
        try {
          listener(data)
        } catch (error) {
          console.error(`[WebSocket] 事件监听器错误 (${event}):`, error)
        }
      })
    }
  }

  /**
   * 开始心跳检测
   */
  startHeartbeat() {
    this.stopHeartbeat()

    this.heartbeatTimer = setInterval(() => {
      if (this.ws && this.ws.readyState === WebSocket.OPEN) {
        this.send({ type: 'ping', timestamp: Date.now() })
      }
    }, this.heartbeatInterval)
  }

  /**
   * 停止心跳检测
   */
  stopHeartbeat() {
    if (this.heartbeatTimer) {
      clearInterval(this.heartbeatTimer)
      this.heartbeatTimer = null
    }
  }

  /**
   * 重新连接
   */
  reconnect() {
    if (this.reconnectTimer) {
      return
    }

    this.reconnectAttempts++
    console.log(`[WebSocket] 尝试重连... (${this.reconnectAttempts}/${this.maxReconnectAttempts})`)

    this.reconnectTimer = setTimeout(() => {
      this.reconnectTimer = null
      this.connect(this.url).catch(error => {
        console.error('[WebSocket] 重连失败:', error)
      })
    }, this.reconnectInterval)
  }

  /**
   * 添加消息到离线队列
   * @param {string} message - 消息内容
   */
  addToQueue(message) {
    if (this.messageQueue.length >= this.maxQueueSize) {
      this.messageQueue.shift() // 移除最早的消息
    }
    this.messageQueue.push(message)
  }

  /**
   * 发送离线队列中的消息
   */
  flushMessageQueue() {
    if (this.messageQueue.length === 0) {
      return
    }

    console.log(`[WebSocket] 发送离线队列中的 ${this.messageQueue.length} 条消息`)

    while (this.messageQueue.length > 0) {
      const message = this.messageQueue.shift()
      this.send(message)
    }
  }

  /**
   * 断开连接
   * @param {number} code - 关闭代码
   * @param {string} reason - 关闭原因
   */
  disconnect(code = 1000, reason = 'Normal closure') {
    console.log('[WebSocket] 主动断开连接')

    // 清除重连定时器
    if (this.reconnectTimer) {
      clearTimeout(this.reconnectTimer)
      this.reconnectTimer = null
    }

    // 停止心跳
    this.stopHeartbeat()

    // 重置重连次数
    this.reconnectAttempts = this.maxReconnectAttempts

    // 关闭 WebSocket 连接
    if (this.ws) {
      this.ws.close(code, reason)
      this.ws = null
    }

    this.isConnected = false
  }

  /**
   * 获取连接状态
   * @returns {boolean} - 是否已连接
   */
  getConnectionState() {
    return this.isConnected && this.ws && this.ws.readyState === WebSocket.OPEN
  }

  /**
   * 获取 WebSocket 实例
   * @returns {WebSocket|null} - WebSocket 实例
   */
  getWebSocket() {
    return this.ws
  }

  /**
   * 清理资源
   */
  destroy() {
    console.log('[WebSocket] 清理资源')

    // 断开连接
    this.disconnect()

    // 清除所有监听器
    this.messageHandlers.clear()
    this.eventListeners.clear()

    // 清空消息队列
    this.messageQueue = []
  }
}

// 创建单例实例
const wsManager = new WebSocketManager()

// 导出默认实例
export default wsManager

// 导出类（如需创建多个实例）
export { WebSocketManager }